
// === uuAltCSSPlus ===
// depend: uuMeta, uuQuery, uuStyle, uuStyleSheet, uuAltCSS, uuColor,
//         uuCanvas, uuLayer
/*
window.UUALTCSS_IMAGE_DIR = "."
 */
(function() {
var _altcssplus, // inner namespace
    _mm = uuMeta,
    _mix = _mm.mix,
    _ss = uuStyleSheet,
    _query = uuQuery,
    _style = uuStyle,
    _color = uuColor,
    _win = window,
    _doc = document,
    _ie = _mm.ie,
    _float = parseFloat,
    _uaver = _mm.uaver,
    _runstyle = _mm.runstyle,
    _ssid = "uuAltCSSPlus",
    _imgdir = _win.UUALTCSS_IMAGE_DIR || ".",
    _spacer = _imgdir.replace(/\/+$/, "") + "/1dot.gif",
    _enableShadow = _mm.gecko191 || _mm.webkit522 || (_ie && _mm._slver),
    // enable functions
    _enable = {
      hover:    (_ie && _uaver < 7) ?  0x10 : 0, // IE6 :hover
      stdcare:  (_ie && _uaver < 7) ?  0x20 : 0, // IE6 position: absolute bug
      posfxd:   (_ie && _uaver < 7) ?  0x40 : 0, // IE6 position: fixed
      alphapng: (_ie && _uaver < 7) ?  0x80 : 0, // IE6 trans alpha.png
      maxmin:   (_ie && _uaver < 7) ? 0x100 : 0, // IE6 max-width
      opacity:  (_ie && _uaver < 9) ? 0x200 : 0, // IE6-IE8 opacity:
      disptbl:  (_ie && _uaver < 8) ? 0x400 : 0, // IE6-IE7 display: table
      bradius:  (_mm.canvas && !(_mm.webkit522 || _mm.gecko191))
                                    ? 0x800 : 0, // -webkit-border-radius:
      boxshadow:(_mm.canvas && !(_mm.webkit522 || _mm.gecko191))
                                    ? 0x1000 : 0, // -webkit-box-shadow:
      gradient: (_mm.canvas && !_mm.webkit530)
                                    ? 0x2000 : 0, // -webkit-gradient:
      boxreflect:(_mm.canvas && !_mm.webkit530)
                                    ? 0x4000 : 0, // -webkit-box-reflect:
      bimage:   (_mm.canvas && !_mm.webkit522)
                                    ? 0x8000 : 0  // -webkit-border-image:
    },
    _deny = 0, // 1: deny removeChild
    _plan = { delay: [], alphapng: [], disptbl: [], posfxd: [],
              maxmin: [], boxshadow: [] },
    _resizeLock = 0,
    _find = {
      // find property
      prop: {
        display: 1,
        position: 2,
        "background-image": 3,
        opacity: _enable.opacity,
        "box-shadow":             _enable.boxshadow,
        "border-radius":          _enable.bradius,
        "-webkit-box-shadow":     _enable.boxshadow,
        "-webkit-border-radius":  _enable.bradius
      },
      // find value
      display:    { table: _enable.disptbl },
      position:   { fixed: _enable.posfxd },
      "background-image": [ "-webkit-gradient", _enable.gradient ]
    },
    TRANSPARENT = "transparent",
    TRIM = /^\s+|\s+$/g,
    MT = "marginTop",
    ML = "marginLeft",
    MR = "marginRight",
    MB = "marginBottom",
    BTW = "borderTopWidth",
    BLW = "borderLeftWidth",
    BRW = "borderRightWidth",
    BBW = "borderBottomWidth",
    BTC = "borderTopColor";

// find keyword
function find(pair, expr) {
  var bits = 0, prop = {}, v, w, i = 0, j, jz, ary;

  while ( (v = pair[i++]) ) {
    switch (w = _find.prop[v.prop] || 0) {
    case 1: bits |= _find.display[v.val]; break;
    case 2: bits |= _find.position[v.val]; break;
    case 3:
      ary = _find["background-image"];
      for (j = 0, jz = ary.length; j < jz; j += 2) {
        if (v.val.indexOf(ary[j]) >= 0) {
          bits |= ary[j + 1];
        }
      }
      prop[v.prop] = v.val;
      break;
    default:
      bits |= w;
      prop[v.prop] = v.val;
    }
  }
  if (_ie) {
    if (/:hover/.test(expr)) {
      bits |= _enable.hover;
    }
  }
  return { bits: bits, prop: prop };
}

function resize() {
  if (!_resizeLock) {
    _resizeLock = 1;
    setTimeout(function() {
      _enable.posfxd && posfxdRecalc();
      _enable.maxmin && maxminRecalc();
      setTimeout(function() { _resizeLock = 0; }, 0); // delay unlock
    }, 40);
  }
}

_altcssplus = {
  init: function(context) {
    _enable.stdcare && stdcarePlan(context);

    if (_enable.posfxd) {
      _plan.delay.push(function() {
        _ss.create(_ssid);
        _ss.insertRule(_ssid, ".uuposfix", // not "uucssposfix"
          ("z-index:5000;" +
           "behavior:expression(" +
           "this.style.pixelTop=document.#.scrollTop+this.uuCSSPosFxd.vpx," +
           "this.style.pixelLeft=document.#.scrollLeft+this.uuCSSPosFxd.hpx)").
          replace(/#/g, _mm.quirks ? "body" : "documentElement")
        );
      });
    }
  },

  makePlan: function(nodeList, revalidate, context) {
    if (!revalidate) {
      _enable.alphapng && alphapngPlan(context);
    }
  },

  prevalidate: function(nodeList, revalidate, context) {
    var i, iz;

    if (_plan.delay.length) {
      for (i = 0, iz = _plan.delay.length; i < iz; ++i) {
        _plan.delay[i]();
      }
      _plan.delay = []; // clear
      _enable.stdcare = 0;
    }
    if (!revalidate) {
      _enable.alphapng && alphapngDo(context);
    }
  },

  postvalidate: function(nodeList, revalidate, context) {
    var node, bits, prop, i = 0, iz = nodeList.length;

    for (; i < iz; i += 2) {
      node = nodeList[i];
      bits = nodeList[i + 1].bits;
      prop = nodeList[i + 1].prop;

      if (bits & _enable.opacity) {
        opacity(node);
      }
      if (bits & _enable.posfxd) {
        posfxd(node);
      }
      if (!revalidate) {
        if (bits & _enable.disptbl) {
          _plan.disptbl.push(node); // stock
        }
        if (bits & _enable.hover) {
          (function(node) {
            _mm.event.bind(node, "mouseenter", function(evt) {
              node.className += node.uuCSSHover;
            });
            _mm.event.bind(node, "mouseleave", function(evt) {
              node.className =
                  node.className.replace(/\s*uucsshover[\d]+/g, "");
            });
          })(node);
        }
        if (bits & (_enable.boxshadow | _enable.bradius |
                    _enable.gradient)) {
          _plan.boxshadow.push(node, prop); // stock
        }
      }
    }
    if (!revalidate) {
      _enable.disptbl && disptbl();
      _enable.boxshadow && boxshadow();
    }
    _enable.maxmin && maxmin(context);


    // window.resize handler
    if (!revalidate) {
      if (_enable.posfxd || _enable.maxmin) {
        _mm.event.bind(_win, "resize", resize);
      }
    }
  }
};

// ---------------------------------------------------------
// care: position: absolute bug(cannot select text)
//       smooth scroll
//       background image cache
// for IE6
function stdcarePlan(context) {
  function markup(elm) {
    _plan.delay.push(function() {
      var st = elm.style;
      // text selection bug
      if (!_mm.quirks) {
        st.height = "100%";
//      st.margin  = "0"; // ToDo
//      st.padding = "0"; // ToDo
      }
      st.backgroundAttachment = "fixed"; // smooth scroll
      !_style.getBGImg(elm) && (st.backgroundImage = "url(none)");
    });
  }
  markup(_query.tag("html")[0]); // <html>
  markup(_doc.body);             // <body>
  _plan.delay.push(function() {
    _doc.execCommand("BackgroundImageCache", false, true);
  });
}

// ---------------------------------------------------------
// care: opacity
// for IE6, IE7, IE8
function opacity(elm) {
  var v = elm.style.opacity || elm.currentStyle.opacity;

  _style.setOpacity(elm, _float(v) || 1.0);
}

// ---------------------------------------------------------
// care: "position: fixed"
// for IE6
function posfxd(elm) {
  if ("uuCSSPosFxd" in elm) { return; } // already fixed

  var vp = _style.getViewport(), rect = _style.getRect(elm),
      cs = elm.currentStyle,
      v = cs.top  !== "auto", // vertical
      h = cs.left !== "auto", // horizontal
      pxfn = _style.getPixel;

  _plan.posfxd.push(elm); // mark

  elm.uuCSSPosFxd = { // bond
    mode: (v ? 1 : 2) | (h ? 4 : 8), // 1:top, 2:bottom, 4:left, 8:right
    vcss: v ? cs.top : cs.bottom,
    hcss: h ? cs.left : cs.right,
    vpx: v ? (pxfn(elm, "paddingTop") + pxfn(elm, "top"))
           : (vp.h - rect.oh - pxfn(elm, "bottom")),
    hpx: h ? (pxfn(elm, "paddingLeft") + pxfn(elm, "left"))
           : (vp.w - rect.ow - pxfn(elm, "right"))
  };
  elm.className += " uuposfix";
  elm.style.position = "absolute"; // position:fixed -> position:absolute
}

function posfxdRecalc() {
  var ary = [], v, w, i = 0, iz = _plan.posfxd.length,
      vp = _style.getViewport(), cs, p;

  for (; i < iz; ++i) {
    v = _plan.posfxd[i];
    if (v && (p = v.uuCSSPosFxd)) {
      cs = v.currentStyle;
      w = _style.toPixel(v, p.vcss, 1);
      p.vpx = (p.mode & 0x1) ? (_style.getPixel(v, "paddingTop") + w)
                             : (vp.h - v.offsetHeight - w);
      w = _style.toPixel(v, p.hcss, 1);
      p.hpx = (p.mode & 0x4) ? (_style.getPixel(v, "paddingLeft") + w)
                             : (vp.w - v.offsetWidth - w);
      ary.push(v);
    }
  }
  // http://www.microsoft.com/japan/msdn/columns/dude/dude061198.aspx
  ary.length && _doc.recalc(true); // update
  _plan.posfxd = ary;
}

// ---------------------------------------------------------
// care: <img src="alpha.png" />
//       <div class="alpha" style="background-image: url(alpha.png)">
// for IE6
function alphapngPlan(context) {
  function clickable(elm) {
    function fix(e) {
      switch (tags[e.tagName.toLowerCase()] || 0) {
      case 1: fixary.push(e, 1); // break;
      case 2: (e.currentStyle.position === "static") && fixary.push(e, 2);
      }
    }
    fix(elm);
    for (var v = elm.firstChild; v; v = v.nextSibling) {
      if (v.nodeType === 1) {
        fix(v);
        v.firstChild && clickable(v);
      }
    }
  }
  function filter(elm, src, method) {
    return [" progid:DXImageTransform.Microsoft.AlphaImageLoader",
            "(src='", src, "',sizingMethod='", method, "')"].join("");
  }

  var rv = [], fixary = [], node, v, i, bg,
      tags = { a: 1, input: 2, select: 2, textarea: 2 };

  node = _query('img[src/="_\\.png$"i]', context), i = 0;
  while ( (v = node[i++]) ) {
    rv.push({ type: 1, elm: v, filter: filter(v, v.src, "image"),
              orgw: v.width, orgh: v.height });
    clickable(v);
  }

  node = _query('input[type=image][src/="_\\.png$"i]', context), i = 0;
  while ( (v = node[i++]) ) {
    rv.push({ type: 2, elm: v, filter: filter(v, v.src, "image") });
    clickable(v);
  }

  // _query('.alphabg{backgroundImage/="_\\.png$"i}')
  node = _query.className("alphabg", context), i = 0;
  while ( (v = node[i++]) ) {
    bg = _style.getBGImg(v);
    if (/_\.png$/i.test(bg)) {
      rv.push({ type: 3, elm: v, filter: filter(v, bg, "crop") });
      clickable(v);
    }
  }
  rv.push({ type: 4, fix: fixary });

  _plan.alphapng = rv;
}

function alphapngDo(context) {
  var hash, v, w, i = 0, j, jz;

  while ( (hash = _plan.alphapng[i++]) ) {
    v = hash.elm;
    switch (hash.type) {
    case 1:
      v.style.filter += hash.filter;
      v.src = _spacer;
      v.width = hash.orgw;
      v.height = hash.orgh;
      break;
    case 2:
      v.style.filter += hash.filter;
      v.src = _spacer;
      v.style.zoom = 1;
      break;
    case 3:
      v.style.filter += hash.filter;
      v.style.backgroundImage = "url(" + _spacer + ")";
      v.style.zoom = 1;
      break;
    case 4:
      for (j = 0, jz = hash.fix.length; j < jz; j += 2) {
        w = hash.fix[j];
        switch (hash.fix[j + 1]) {
        case 1: w.style.cursor = "pointer"; break;
        case 2: w.style.position = "relative";
        }
      }
    }
  }
}

// ---------------------------------------------------------
// care: max-width, min-width, max-height, min-height
// for IE6
function maxmin(context) {
  maxminMarkup(context);
  maxminRecalc();
}

function maxminMarkup(context) {
  var rv = [], maxWidth, minWidth, maxHeight, minHeight,
      node = _query.tag("*", context),
      v, i = 0, cs, rex1 = /^(inherit|none|auto)$/,
      blockLevel = { block: 1, "inline-block": 1, "table-cell": 1 };

  while ( (v = node[i++]) ) {
    cs = v.currentStyle;
    if (blockLevel[cs.display]) {
      maxWidth  = cs["max-width"]  || ""; // length | % | none | inherit
      minWidth  = cs["min-width"]  || ""; // length | % | inherit
      maxHeight = cs["max-height"] || ""; // length | % | none | inherit
      minHeight = cs["minHeight"];        // length | % | inherit
                                          //   (ie6 default "auto")
      rex1.test(maxWidth)  && (maxWidth  = "");
      rex1.test(minWidth)  && (minWidth  = "");
      rex1.test(maxHeight) && (maxHeight = "");
      rex1.test(minHeight) && (minHeight = "");

      if (maxWidth  === "" && minWidth  === "" &&
          maxHeight === "" && minHeight === "") {
        if ("uuCSSBoostMaxMin" in v) {
          delete v["uuCSSBoostMaxMin"];
        }
        continue; // exclude
      }

      _mix(v, {
        uuCSSBoostMaxMin: {}
      }, 0, 0);
      _mix(v.uuCSSBoostMaxMin, {
        maxWidth:  maxWidth,
        minWidth:  minWidth,
        maxHeight: maxHeight,
        minHeight: minHeight
      });
      _mix(v.uuCSSBoostMaxMin, {
        orgWidth:  v.currentStyle.width,
        orgHeight: v.currentStyle.height
      }, 0, 0);
      rv.push(v);
    }
  }
  _plan.maxmin = rv;
}

function maxminRecalc() {
  var elm, i = 0, hash,
      calcMaxWidth, calcMinWidth, calcMaxHeight, calcMinHeight,
      run, width, height, rect;

  while ( (elm = _plan.maxmin[i++]) ) {
    hash = elm.uuCSSBoostMaxMin;

    calcMaxWidth  = maxminRecalcSize(elm, hash, "maxWidth", 1);
    calcMinWidth  = maxminRecalcSize(elm, hash, "minWidth", 1);
    calcMaxHeight = maxminRecalcSize(elm, hash, "maxHeight");
    calcMinHeight = maxminRecalcSize(elm, hash, "minHeight");

    // recalc
    if (calcMaxWidth || calcMinWidth) {

      // recalc max-width
      if (calcMinWidth > calcMaxWidth) {
        calcMaxWidth = calcMinWidth;
      }

      // recalc width
      // width: auto !important
      run = elm.runtimeStyle.width;  // keep runtimeStyle.width
      elm.runtimeStyle.width = hash.orgWidth;
      elm.style.width = "auto";
      rect = elm.getBoundingClientRect(); // re-validate
      width = rect.right - rect.left;

      elm.style.width = hash.orgWidth; // o
      elm.runtimeStyle.width = run; // restore style

      // recalc limits
      if (width > calcMaxWidth) {
        width = calcMaxWidth;
        elm.style.pixelWidth = width;
      } else if (width < calcMinWidth) {
        width = calcMinWidth;
        elm.style.pixelWidth = width;
      }
    }

    if (calcMaxHeight || calcMinHeight) {

      // recalc max-height
      if (calcMinHeight > calcMaxHeight) {
        calcMaxHeight = calcMinHeight;
      }

      // recalc height
      // height: auto !important
      run = elm.runtimeStyle.height;  // keep runtimeStyle.height
      elm.runtimeStyle.height = hash.orgHeight;
      elm.style.height = "auto";
      rect = elm.getBoundingClientRect(); // re-validate
      height = rect.bottom - rect.top;

      elm.style.height = hash.orgHeight; // o
      elm.runtimeStyle.height = run; // restore style

      // recalc limits
      if (height > calcMaxHeight) {
        height = calcMaxHeight;
        elm.style.pixelHeight = height;
      } else if (height < calcMinHeight) {
        height = calcMinHeight;
        elm.style.pixelHeight = height;
      }
    }
  }
}

function maxminRecalcSize(elm, hash, prop, horizontal) {
  var rv = 0, rect;

  if (hash[prop] !== "") {
    if (/[\d\.]+%$/.test(hash[prop])) {
      rect = elm.parentNode.getBoundingClientRect();
      rv = _float(hash[prop]);
      rv = (horizontal ? (rect.right - rect.left)
                       : (rect.bottom - rect.top)) * rv / 100;
    } else {
      rv = _style.toPixel(elm, hash[prop], 1);
    }
  }
  return rv;
}

// ---------------------------------------------------------
// care: display:table, display: table-cell
// for IE6, IE7
function disptbl() {
  var node = _plan.disptbl, v, i, j, iz,
      tbl, row, cell;

  for (i = 0, iz = node.length; i < iz; ++i) {
    v = node[i];
    tbl = _doc.createElement("table");
    // copy attrs
    tbl.id = v.id;
    tbl.title = v.title;
    tbl.className = v.className;
    // copy style
    tbl.style.cssText = v.style.cssText;
    tbl.style.borderCollapse = "collapse";

    row = tbl.insertRow(); // add last row

    for (j = v.firstChild; j; j = j.nextSibling) {
      cell = row.insertCell(); // add last cell
      // copy attrs
      cell.id = j.id;
      cell.title = j.title;
      cell.className = j.className;
      // copy style
      cell.style.cssText = j.style.cssText;
      cell.style.margin = "0"; // force margin: 0
      // copy event handler(click, dblclick only)
      cell.onclick = j.onclick;
      cell.ondblclick = j.ondblclick;

      while (j.firstChild) {
        cell.appendChild(j.removeChild(j.firstChild));
      }
    }
    v.parentNode.replaceChild(tbl, v);
  }
  _plan.disptbl = []; // clear
}

// ---------------------------------------------------------
// care: box-shadow: color offsetX offsetY blur
// care: border-radius: radius
// care: background: -webkit-gradient(linear, start, end,
//                                    from(beginColor),
//                                    [color-stop(pos, color),]
//                                    to(endColor));
// care: -webkit-gradient(<type>, <point> [, <radius>]?, <point> [, <radius>]? [, <stop>]*)
//       type ::= "linear" / "radial"
//       point ::= "A B"
//       A ::= number / percentages / keyword
//       keyword ::= "top" / "bottom" / "left" / "right"
// for All browser

function boxshadow() {
  var nodeProp = _plan.boxshadow, v, i = 0, iz = nodeProp.length,
      cs, css, prop,
      topx = _style.toPixel;

  for (; i < iz; i += 2) {
    v = nodeProp[i];     // node
    css = nodeProp[i + 1]; // prop
    cs = _ie ? v[_runstyle]
             : _runstyle(v, "");
    prop = {};
    _mm.mix(prop, {
      rect: _style.getRect(v),
      bgimg: _style.getBGImg(v),
      radius: topx(v, cs["border-radius"] ||
                      css["border-radius"] ||
                      css["-webkit-border-radius"]),
      bgcolor: _style.getBGColor(v, 1),
      marginTop: topx(v, cs[MT]),
      marginLeft: topx(v, cs[ML]),
      marginRight: topx(v, cs[MR]),
      marginBottom: topx(v, cs[MB]),
      borderTopWidth: topx(v, cs[BTW]),
      borderLeftWidth: topx(v, cs[BLW]),
      borderRightWidth: topx(v, cs[BRW]),
      borderBottomWidth: topx(v, cs[BBW]),
      borderTopColor: _color.parse(cs[BTC])[0],
      smg: 4, // shadow margin
      boxw: 0,
      boxh: 0
    });
    addBoxShadowParam(v, cs, css, prop);
    addGradientParam(v, cs, css, prop);

    prop.boxw = prop.rect.w + prop[BLW] + prop[BRW];
    prop.boxh = prop.rect.h + prop[BTW] + prop[BBW];

    if (_ie && _uaver < 8) { // IE6, IE7 bug
      prop.boxw = prop.rect.w;
      prop.boxh = prop.rect.h;
    }

    if (_ie) {
      if (!prop.sox && !prop.soy && prop.sblur) {
        prop.sox = 1;
        prop.soy = 1;
      }
    }
    boxShadow2(v, prop);
  }
}

function boxShadow2(node, pr) {
  function draw() {
    var box = layer.refLayer("b"),
        bs = box.style, ns = node.style,
        zone = pr.sblur + pr.smg;

    if (pr.radius) {
      // --- border-radius: + box-shadow: ---
      // draw border + drop shadow
      if (!_enableShadow) {
        layer.save().
              fills(pr.scolorArray[0]).
              alphas(pr.scolorArray[1]).
              box(zone + pr.sox, zone + pr.soy, pr.boxw, pr.boxh,
                  pr.radius + (pr.radius < 40 ? 4 : 0)).
              restore();
      }
      layer.save().
            fills(pr[BTC]).
            shadows(pr.scolor, pr.sox, pr.soy, pr.sblur).
            box(zone, zone, pr.boxw, pr.boxh,
                pr.radius + (pr.radius < 40 ? 4 : 0)).
      // reset shadow
            shadows(TRANSPARENT, 0, 0, 0).
      // draw image or fill
            fills(pr.bgimg ? layer.pattern(img) : pr.bgcolor[0]).
            box(zone + pr[BLW], zone + pr[BTW],
                pr.boxw - pr[BLW] - pr[BRW],
                pr.boxh - pr[BTW] - pr[BBW], pr.radius).
            restore();
      // bg setting
      ns.backgroundColor = TRANSPARENT;
      ns.backgroundImage = "none";
    } else {
      // --- box-shadow: ---
      if (!_enableShadow) {
        layer.save().
              fills(pr.scolorArray[0]).
              alphas(pr.scolorArray[1]).
              box(zone + pr.sox, zone + pr.soy,
                  pr.boxw, pr.boxh, pr.radius).
              restore();
      }

      if (pr.gradtype) {
        switch (pr.gradtype) {
        case 1:
          layer.save().
                fills(layer.linearGrad(pr.gradpos[0], pr.gradpos[1],
                                       pr.gradpos[2], pr.gradpos[3],
                                       pr.gradoffset, pr.gradcolor)).
                box(zone, zone - pr.smg,
                    pr.boxw, pr.boxh + pr.smg * 2, pr.radius).
                restore();
          break;
        case 2:
          layer.save().
                fills(layer.radialGrad(pr.gradpos[0], pr.gradpos[1],
                                       pr.gradradius[0],
                                       pr.gradpos[2], pr.gradpos[3],
                                       pr.gradradius[1],
                                       pr.gradoffset, pr.gradcolor)).
                box(zone, zone - pr.smg,
                    pr.boxw, pr.boxh + pr.smg * 2, pr.radius).
                restore();
        }
        ns.backgroundColor = TRANSPARENT;
      } else {
        layer.save().
              fills(pr[BTC]).
              shadows(pr.scolor, pr.sox, pr.soy, pr.sblur).
              box(zone, zone, pr.boxw, pr.boxh, pr.radius).
              restore();
        // bg setting
        ns.backgroundColor = pr.bgcolor[0];
      }
    }

    box.appendChild(node);

    if (0) { // debug
      view.style.outline="1px solid red";
      bs.outline = "3px dotted black";
      ns.outline = "1px solid pink";
      layer.refLayer("a").style.border = "1px solid tomato";
    }

    bs.position = "relative";
    bs.left     = (zone + pr[BLW]) + "px";
    bs.top      = (zone + pr[BTW]) + "px";
    bs.width    = pr.rect.w + "px";
    bs.heigth   = pr.rect.h + "px";
    if (_ie && _uaver < 8) {
      bs.pixelWidth  = pr.rect.w - pr[BLW] - pr[BRW];
      bs.pixelHeigth = pr.rect.h - pr[BTW] - pr[BBW];
    }

    ns.border  = "0px none";
    ns.margin  = "0";
    ns.display = "block";
    layer.showLayer();

    if (_ie) {
      if ((layer.refLayer("a").uuCanvasType === "SL2D")) {
        _deny = 1;
      }
    }
  }

  var view = _doc.createElement("div"), vs = view.style,
      layer, img, zone = pr.sblur * 2 + pr.smg * 2;

  node.style.display = "none";
  node.parentNode.insertBefore(view, node);
  vs.padding = "0";
  vs[MT] = (-pr.smg - pr.sblur - pr.smg) + "px";
  vs[ML] = (pr[ML] - pr.sblur - pr.smg) + "px";
  vs[MR] = (pr[MR] - pr.sblur) + "px";
  vs[MB] = (pr[MB] - pr.sblur) + "px";

  layer = new uuLayer(view, pr.rect.w + zone + pr[BLW] + pr[BRW],
                            pr.rect.h + zone + pr[BTW] + pr[BBW]);
  layer.createLayer("a", "canvas", 1); // create hidden layer
  layer.createLayer("b", "div", 1); // creat ehidden layer

  if (pr.bgimg && pr.radius) {
    img = new Image();
    img.onload = function() {
      uuCanvas.ready(draw);
      img.onload = "";
    };
    img.setAttribute("src", pr.bgimg);
  } else {
    uuCanvas.ready(draw);
  }
}

function addBoxShadowParam(elm, cs, css, prop) {
  // parse: box-shadow: color offsetX offsetY blur

  var ary, scolor, sox, soy, sblur,
      topx = _style.toPixel,
      dummy = "transparent 0 0 0";

  // parse box-shadow:
  //    "rgba( 0, 0, 0, 0 )  0px  0px  0px"
  //        v
  //    ["rgba(0,0,0,0)", "0px", "0px", "0px"]

  ary = (cs["box-shadow"] ||
         css["box-shadow"] || css["-webkit-box-shadow"] || dummy).
        replace(/\(\s*/, "(").replace(/\s*\)/, ")").
        replace(/\s*,\s*/g, ",").split(/\s+/);

  scolor = /^\d/.test(ary[0]) ? ary.pop() : ary.shift();
  sox    = ary.shift() || 0;
  soy    = ary.shift() || 0;
  sblur  = ary.shift() || 0;

  _mm.mix(prop, {
    scolorArray: _color.parse(scolor), // [#ffffff, alpha]
    scolor: scolor, // original shadow color
    sox:    topx(elm, sox),   // shadow offset x
    soy:    topx(elm, soy),   // shadow offset y
    sblur:  topx(elm, sblur)  // shadow blur
  });
}

function addGradientParam(elm, cs, css, prop) {
  // parse:
  //    -webkit-gradient(<type>, <point> [, <radius>]?,
  //                             <point> [, <radius>]? [, <stop>]*)
  function getPos(m, lt, rb, num, per) {
    var size = (pos.length & 1) ? prop.rect.h
                                : prop.rect.w;
    pos.push(lt ? 0 :
             rb ? size :
             per ? (size * _float(num)) : _float(num));
    return "";
  }
  function getRadius(m, a1) {
    radius.push(_float(a1));
    return "";
  }

  var type = 0, pos = [], radius = [],
      offset = [], color = [], expr,
      match = /^-webkit-gradient\((.*)\)$/.exec(css["background-image"]),
      GRAD_TYPE = /^(?:(linear)|radial)\s*,?/,
      GRAD_POS1 = /(?:(left)|(right)|([\d\.]+)(%)?)\s+/,
      GRAD_POS2 = /(?:(top)|(bottom)|([\d\.]+)(%)?)\s*,?/,
      GRAD_RADIUS = /([\d\.]+)\s*,/,
      GRAD_FROM = /from\(\s*(rgba?\([^\)]+\)|#[\w]+)\s*\)/,
      GRAD_TO   = /to\(\s*(rgba?\([^\)]+\)|#[\w]+)\s*\)/,
      GRAD_STOP =
          /color-stop\(\s*([\d\.]+)\s*,\s*(rgba?\([^\)]+\)|#[\w]+)\s*\)/g;

  if (match) {
    expr = match[1].replace(GRAD_TYPE, function(m, l) {
      type = l ? 1 : 2;
      return "";
    }).replace(GRAD_POS1, getPos).
       replace(GRAD_POS2, getPos);

    if (type === 2) { // radial
      expr = expr.replace(GRAD_RADIUS, getRadius);
    }

    expr = expr.replace(GRAD_POS1, getPos).
                replace(GRAD_POS2, getPos);

    if (type === 2) {
      expr = expr.replace(GRAD_RADIUS, getRadius);
    }

    expr.replace(TRIM, "").
      replace(GRAD_FROM, function(m, c) {
        offset.push(0);
        color.push(c); return "";
      }).
      replace(GRAD_TO,   function(m, c) {
        offset.push(1);
        color.push(c); return "";
      }).
      replace(GRAD_STOP, function(m, p, c) {
        offset.push(_float(p));
        color.push(c); return "";
      });
  }
  _mm.mix(prop, {
    gradtype:   type,   // 0: none, 1: linear, 2: radial
    gradpos:    pos,    // [pos1x, pos1y, pos2x, pos2y]
    gradradius: radius, // [radius1, radius2]
    gradoffset: offset, // [0, ...]
    gradcolor:  color   // [{ r, g, b, a}, ... ]
  });
}

// --- initialize ---

// --- export ---
_win.uuAltCSSPlus = _altcssplus;
_altcssplus.find = find;
_altcssplus.deny = function() { return _deny; };

})(); // uuAltCSSPlus scope
